# -*- encoding: utf-8 -*-
"""
    Created by Rachel on 2025/03/06
"""
from ast import literal_eval

from flask import request, current_app

from applications.api import RegisterBlueprint as api
from applications.ext.init_sqlalchemy import db
from applications.libs.expression import Expression
from applications.libs.http_code import fail_api, success_api, error


@api.public.route("/create", methods=["POST"])
@error
def create():
    """
    通用创建接口
    请求体，此处已创建user表数据为例, 不建议通过该接口创建用户数据
    {
        "model_name": "user",
        "create_data": [
            {"account": "1", "password": "1234556789", "username": "张三"},
            {"account": "2", "password": "1234556789", "username": "赵三"},
            {"account": "3", "password": "1234556789", "username": "王三"}
        ]
    }
    :return:
    """
    model_name = request.json.get("model_name")
    if not model_name:
        return fail_api("请传入模型名称")

    create_data = request.json.get("create_data")
    if not len(create_data):
        return fail_api(msg="请传入创建数据")

    class_ = current_app.models[model_name]

    with db.auto_commit():
        class_.multi_create(create_data)
    return success_api()


@api.public.route("/update", methods=["POST"])
@error
def update():
    """
    通用更新接口
    请求体，此处已user为例
    {
        "model_name": "user",
        "primary_key": "account",
        "update_data": [
            {"account": "1", "email": "123@qq.com"},
            {"account": "2", "username": "黑三"}
        ]
    }
    :return:
    """
    model_name = request.json.get("model_name")
    if not model_name:
        return fail_api("请传入模型名称")

    update_data = request.json.get("update_data")
    if not len(update_data):
        return fail_api(msg="请传入更新数据")

    primary_key = request.json.get("primary_key")
    if not primary_key:
        return fail_api(msg="请传入主键值")

    class_ = current_app.models[model_name]
    with db.auto_commit():
        for record in update_data:
            # 获取修改的记录ID
            if not record.__contains__(primary_key):
                return fail_api(msg="未检测到主键, 请检查传入数据")
            primary_value = record.get(primary_key, None)
            if not primary_value:
                return fail_api(msg="请传入需要修改数据的主键值")

            record.pop(primary_key)

            update_obj = class_.query.filter(getattr(class_, primary_key) == primary_value).first()

            if not update_obj:
                return fail_api(msg="未查找需要修改的单据")
            update_obj.write(is_commit=False, **record)
    return success_api()


@api.public.route("/delete", methods=["POST"])
@error
def delete():
    """
    通用删除接口
    请求体，此处已user为例
        {
            "model_name": "user",
            "primary_key": "account",
            "delete_data": ["1", "2"]
        }
    :return
    """
    model_name = request.json.get("model_name")
    if not model_name:
        return fail_api("请传入模型名称")

    primary_key = request.json.get("primary_key")
    if not primary_key:
        return fail_api(msg="请传入主键值")

    delete_data = request.json.get("delete_data")
    if not len(delete_data):
        return fail_api(msg="请传入删除数据")

    class_ = current_app.models[model_name]
    with db.auto_commit():
        class_.query.filter(getattr(class_, primary_key).in_(delete_data)).delete(synchronize_session=False)
    return success_api()


@api.public.route("/search", methods=["POST"])
@error
def search():
    """
    通用查询接口
    domain参数说明
        in 条件格式: {"字段名": "可查看值列表"},
        =  条件格式: {"字段名": "字符串或数字或浮点数"}
        like、ilike、不等于……条件格式: {"字段名": {"like": "值", "not_equal": "a"}}
        区间格式 格式 {"字段4": {"min": "", "max": ""}}
    请求方式数据 {
            "model_name": "user",
            "search_fields": [
                "id", "account", "username", "email"
            ],
            "domain": {"account": [1,2,3,4,5,6,7]},
            "page": 1,
            "size": 2,
            "order_field": "id",
            "order_type": "asc"
        }
    :return:
    """
    model_name = request.json.get("model_name")
    if not model_name:
        return success_api(msg="请传入模型名称")

    search_fields = request.json.get("search_fields")

    if not search_fields:
        return success_api(msg="请传入模型名称")

    class_ = current_app.models[model_name]

    query = db.session.query(*[getattr(class_, field) for field in search_fields])

    filter_array = []

    domain = request.json.get("domain")
    if domain:
        obj = Expression(class_, domain)
        filter_array.extend(obj.parse())

    query = query.filter(*filter_array)

    order_field, order_type = request.json.get("order_field"), request.json.get("order_type")
    if order_field and order_type:
        query = query.order_by(
            getattr(class_, order_field).desc() if order_type.upper() == "DESC" else getattr(class_, order_field).asc()
        )

    page, size = request.json.get("page"), request.json.get("size")
    pagination = query.paginate(page, size)

    recv_data = []
    for record in pagination.items:
        content = dict(zip(record.keys(), record))
        recv_data.append(content)

    return success_api(result={"search_data": recv_data, "total": pagination.total})
